package com.storage.web.controller.system;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.storage.common.annotation.Log;
import com.storage.common.config.Global;
import com.storage.common.core.controller.BaseController;
import com.storage.common.core.domain.AjaxResult;
import com.storage.common.core.domain.ServiceResponse;
import com.storage.common.core.page.TableDataInfo;
import com.storage.common.enums.BusinessType;
import com.storage.common.enums.RoleType;
import com.storage.common.utils.file.FileUploadUtils;
import com.storage.framework.jwt.Constant;
import com.storage.framework.shiro.service.StoragePasswordService;
import com.storage.framework.util.JwtUtil;
import com.storage.framework.util.ShiroUtils;
import com.storage.framework.web.OperationContext;
import com.storage.framework.web.OperationContextHolder;
import com.storage.framework.web.enums.RequestOperation;
import com.storage.system.domain.StorageBrand;
import com.storage.system.domain.StorageUser;
import com.storage.system.domain.StorageUserAgent;
import com.storage.system.service.ISmsService;
import com.storage.system.service.IStorageUserService;
import com.storage.system.service.impl.RedisService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;

/**
 * 用户 信息操作处理
 *
 * @author storage
 * @date 2019-08-18
 */
@Api(tags = "用户相关接口")
@RestController
public class StorageUserController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(StorageUserController.class);

    @Autowired
    private IStorageUserService storageUserService;

    @Autowired
    private StoragePasswordService passwordService;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private RedisService redisService;

    /**
     * 查询用户列表
     */
    @ApiOperation(value = "查询用户列表", notes = "查询用户列表")
    @GetMapping("/system/storageUser/user/list")
    @ResponseBody
    public TableDataInfo list(StorageUser storageUser,
                              @RequestParam(value = "pageNum", required = false) Integer pageNum,
                              @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        ServiceResponse<TableDataInfo> response = storageUserService.selectStorageUserList(storageUser, pageNum, pageSize);
        return response.getData();
    }

    /**
     * 查询业务员列表
     */
    @ApiOperation(value = "查询业务员列表", notes = "查询业务员列表")
    @GetMapping("/system/storageUser/business/list")
    @ResponseBody
    public TableDataInfo businessUserList(@RequestOperation OperationContext context,
                                          StorageUser storageUser,
                                          @RequestParam(value = "pageNum", required = false) Integer pageNum,
                                          @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        ServiceResponse<TableDataInfo> response = storageUserService.selectStorageBusinessUserList(context.getStorageUser(), storageUser, pageNum, pageSize);
        return response.getData();
    }

    /**
     * 新增保存用户(用于添加店铺人员/业务员等场景)
     */
    @ApiOperation(value = "新增保存用户(用于添加店铺人员/业务员等场景)", notes = "新增保存用户(用于添加店铺人员/业务员等场景)")
    @Log(title = "用户", businessType = BusinessType.INSERT)
    @PostMapping("/system/storageUser/user/add")
    @ResponseBody
    public AjaxResult addSave(@RequestOperation OperationContext context,
                              @RequestBody StorageUser addUser) {
        if (StringUtils.isBlank(addUser.getPassword())) {
            return AjaxResult.error("密码不能为空");
        } else if (StringUtils.isBlank(addUser.getPhone())) {
            return AjaxResult.error("电话号码不能为空");
        } else if ( storageUserService.selectUserByPhoneNumber(addUser.getPhone()) != null) {
            return AjaxResult.error("当前电话号码已被占用");
        } else if (addUser.getRole() == RoleType.BUSINESS_USER.getValue()) {
            if (StringUtils.isBlank(addUser.getBusinessCode())) {
                return AjaxResult.error("业务员编码不能为空");
            }
            StorageUser businessUser = storageUserService.selectUserByBusinessCode(addUser.getBusinessCode());
            if (businessUser != null) {
                return AjaxResult.error("业务员编码重复");
            }
        }
        // 设置随机盐
        addUser.setSalt(ShiroUtils.randomSalt());
        // 构建密码
        addUser.setPassword(passwordService.encryptPassword(addUser.getPhone(), addUser.getPassword(), addUser.getSalt()));
        return storageUserService.insertStorageUser(context.getStorageUser(), addUser);
    }

    /**
     * 根据店铺id获取店铺创建人信息
     */
    @ApiOperation(value = "根据店铺id获取店铺创建人信息", notes = "根据店铺id获取店铺创建人信息")
    @GetMapping("/system/user/getShopCreatorInfo")
    @ResponseBody
    public AjaxResult getShopCreatorInfo(@RequestOperation OperationContext context) {
        ServiceResponse<StorageUser> response = storageUserService.getShopCreatorInfo(context.getStorageUser());
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        return AjaxResult.success(response.getData());
    }

    /**
     * 修改保存用户信息
     */
    @ApiOperation(value = "修改保存用户信息", notes = "修改保存用户信息")
    @Log(title = "用户", businessType = BusinessType.UPDATE)
    @PostMapping("/system/storageUser/user/edit")
    @ResponseBody
    public AjaxResult editSave(@RequestOperation OperationContext context,
                               @RequestBody StorageUser storageUser) {
        if (StringUtils.isNotBlank(storageUser.getPassword()) && storageUser.getPassword().length() != 32) {
            // 构建密码
            storageUser.setSalt(ShiroUtils.randomSalt());
            String password = passwordService.encryptPassword(storageUser.getPhone(), storageUser.getPassword(), storageUser.getSalt());
            storageUser.setPassword(password);
        }

        ServiceResponse<StorageUser> response = storageUserService.updateStorageUser(context.getStorageUser(), storageUser);
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        // 更新上下文用户信息
        context.setStorageUser(storageUserService.selectStorageUserById(response.getData().getId()));
        OperationContextHolder.set(context);
        return AjaxResult.success(response.getData());
    }

    /**
     * 修改密码
     *
     */
    @ApiOperation(value = "修改密码", notes = "修改密码")
    @Log(title = "用户", businessType = BusinessType.UPDATE)
    @PostMapping("/system/user/modify/password")
    @ResponseBody
    public AjaxResult editSave(HttpServletRequest request, HttpServletResponse response,
                               @RequestOperation OperationContext context,
                               @RequestBody String json) {
        StorageUser currUser = storageUserService.selectStorageUserById(context.getStorageUser().getId());
        if (currUser == null) {
            return AjaxResult.error("当前账户账号异常");
        }

        JSONObject jsonObject = JSON.parseObject(json);
        String mobile = jsonObject.get("mobile") == null ? null : jsonObject.get("mobile").toString();
        String newPassword = jsonObject.get("newPassword") == null ? null : jsonObject.get("newPassword").toString();
        String identifyCode = jsonObject.get("identifyCode") == null ? null : jsonObject.get("identifyCode").toString();
        if (mobile == null || newPassword == null || identifyCode == null) {
            return AjaxResult.error("电话、新密码、验证都不能为空");
        }

        if (!smsService.checkIsCorrectCode(mobile, identifyCode).isSuccess()) {
            return AjaxResult.error("验证码错误或已过期");
        }

        currUser.setSalt(ShiroUtils.randomSalt());
        currUser.setPassword(passwordService.encryptPassword(currUser.getPhone(), newPassword, currUser.getSalt()));
        ServiceResponse<StorageUser> userResponse = storageUserService.updateStorageUser(context.getStorageUser(), currUser);
        if (!userResponse.isSuccess()) {
            return AjaxResult.error(userResponse.getError());
        }
        currUser = storageUserService.selectStorageUserById(userResponse.getData().getId());
        context.setStorageUser(currUser);
        OperationContextHolder.set(context);

        // 登录模式：pc or mobile
        String type = request.getHeader(Constant.TYPE_HEADER_NAME);
        String token = request.getHeader(Constant.TOKEN_HEADER_NAME);
        // 生成jwtToken
        String jwtToken = JwtUtil.sign(currUser.getPhone(), currUser.getId(), currUser.getPassword(), type);
        redisService.delete(token);
        // 将 token 存入 redis (查询缓存中是否已有该账号的token缓存)
        redisService.setKey(jwtToken, jwtToken, Constant.TOKEN_EXPIRE_TIME);

        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        response.addHeader(Constant.TOKEN_HEADER_NAME, jwtToken);
        currUser.setAuthorization(jwtToken);
        return AjaxResult.success(currUser);
    }

    /**
     * 删除用户
     */
    @ApiOperation(value = "删除用户", notes = "删除用户")
    @Log(title = "用户", businessType = BusinessType.DELETE)
    @GetMapping("/system/storageUser/user/remove")
    @ResponseBody
    public AjaxResult remove(@RequestParam("ids") String ids) {
        return toAjax(storageUserService.deleteStorageUserByIds(ids));
    }


    /**
     * 保存头像
     */
    @ApiOperation(value = "保存头像", notes = "保存头像")
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PostMapping("/system/storageUser/user/updateAvatar")
    @ResponseBody
    public AjaxResult updateAvatar(@RequestOperation OperationContext context,
                                   @RequestParam("avatarfile") MultipartFile file) {
        StorageUser currentUser = context.getStorageUser();
        try {
            if (!file.isEmpty()) {
                String avatar = FileUploadUtils.upload(Global.getAvatarPath(), file);
                currentUser.setAvatar(avatar);
                storageUserService.updateStorageUser(context.getStorageUser(), currentUser);
                currentUser = storageUserService.selectStorageUserById(currentUser.getId());
                context.setStorageUser(currentUser);
                OperationContextHolder.set(context);
                return AjaxResult.success("操作成功", currentUser);
            }
            return error();
        } catch (Exception e) {
            log.error("修改头像失败！", e);
            return error(e.getMessage());
        }
    }

    /**
     * 查询用户-代理商列表(用于上下级对账、上下级管理)
     *
     * @param level
     * @return
     */
    @ApiOperation(value = "查询用户-代理商列表(用于上下级对账、上下级管理)", notes = "查询用户-代理商列表(用于上下级对账、上下级管理)")
    @GetMapping("/system/storageUser/agent/list")
    @ResponseBody
    public TableDataInfo list(@RequestOperation OperationContext context,
                              @RequestParam(value = "level", required = false) Integer level,
                              @RequestParam(value = "type", required = false) String type,
                              @RequestParam(value = "pageNum", required = false) Integer pageNum,
                              @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        ServiceResponse<TableDataInfo> response = storageUserService.selectStorageUserAgentList(context.getStorageUser(), level, type, pageNum, pageSize);
        return response.getData();
    }

    /**
     * 根获取指定代理商开放的品牌
     *
     * @param level
     * @param agentId
     * @return
     */
    @ApiOperation(value = "根获取指定代理商开放的品牌")
    @GetMapping("/system/storageUser/agent/acceptBrand")
    @ResponseBody
    public AjaxResult getAgentRelationByAgentId(@RequestOperation OperationContext context,
                                                @RequestParam(value = "level", required = false) Integer level,
                                                @RequestParam(value = "agentId", required = false) Long agentId) {
        ServiceResponse<List<StorageBrand>> response = storageUserService.getAgentBrands(context.getStorageUser(), level, agentId);
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        return AjaxResult.success(response.getData());
    }

    /**
     * 根获当前代理商或者店铺库存中的所有品牌
     *
     * @return
     */
    @ApiOperation(value = "根获当前代理商或者店铺库存中的所有品牌")
    @GetMapping("/system/storageUser/brand")
    @ResponseBody
    public AjaxResult getAgentBrand(@RequestOperation OperationContext context,
                                    @RequestParam(value = "brandName", required = false) String brandName) {
        ServiceResponse<List<JSONObject>> response = storageUserService.getAgentSelfBrands(context.getStorageUser(), brandName);
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        return AjaxResult.success(response.getData());
    }

    /**
     * 新增保存用户-代理商
     */
    @ApiOperation(value = "新增保存用户-代理商")
    @Log(title = "用户-代理商", businessType = BusinessType.INSERT)
    @PostMapping("/system/storageUser/agent/add")
    @ResponseBody
    public AjaxResult addAgentSave(@RequestOperation OperationContext context,
                                   @RequestBody StorageUserAgent storageUserAgent) {
        if (StringUtils.isBlank(storageUserAgent.getAgentInvitationCode())) {
            return error("邀请码不能为空");
        }

        if (storageUserAgent.getLevel() == null) {
            return error("上下级代理不明确");
        }

        StorageUser storageUser = context.getStorageUser();
        if (Objects.equals(storageUserAgent.getAgentInvitationCode(), storageUser.getPhone())) {
            return error("被添加自己为代理商");
        }
        ServiceResponse<StorageUserAgent> response = storageUserService.insertStorageUserAgent(storageUser, storageUserAgent);
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }

        return AjaxResult.success(response.getData());
    }

    /**
     * 更新代理商信息
     */
    @ApiOperation(value = "更新代理商信息")
    @Log(title = "用户-代理商", businessType = BusinessType.UPDATE)
    @PostMapping("/system/storageUser/agent/update")
    @ResponseBody
    public AjaxResult updateAgent(@RequestOperation OperationContext context,
                                  @RequestBody StorageUserAgent storageUserAgent) {
        return storageUserService.updateStorageUserAgent(context.getStorageUser(), storageUserAgent);
    }

    /**
     * 更新是否开放库存查看状态给指定代理商
     *
     * @param agentId 代理商id
     * @param show    代理商查看当前用户库存权限: 0-不允许代理商查看;1-允许代理商查看库存
     * @return
     */
    @ApiOperation(value = "更新代理商信息")
    @Log(title = "用户-代理商", businessType = BusinessType.UPDATE)
    @GetMapping("/system/storageUser/agent/update")
    @ResponseBody
    public AjaxResult updateStockShow(@RequestOperation OperationContext context,
                                      @RequestParam("agentId") Long agentId, @RequestParam("show") int show) {
        return storageUserService.markStockShowStatus(context.getStorageUser(), agentId, show);
    }

    /**
     * 删除代理商
     */
    @ApiOperation(value = "删除代理商", notes = "删除代理商")
    @Log(title = "用户", businessType = BusinessType.DELETE)
    @GetMapping("/system/storageUser/agent/remove")
    @ResponseBody
    public AjaxResult removeAgent(@RequestOperation OperationContext context,
                                  @RequestParam("ids") String ids,
                                  @RequestParam("level") Integer level) {
        ServiceResponse<Boolean> response = storageUserService.deleteStorageUserAgentByIds(context.getStorageUser(), level, ids);
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        return AjaxResult.success();
    }

    /**
     * 获取推荐人
     */
    @ApiOperation(value = "获取推荐人", notes = "获取推荐人")
    @Log(title = "用户", businessType = BusinessType.DELETE)
    @GetMapping("/system/storageUser/getRecommend")
    @ResponseBody
    public AjaxResult getRecommendBusinessUser(@RequestOperation OperationContext context) {
        ServiceResponse<StorageUser> response = storageUserService.getRecommendBusinessUser(context.getStorageUser());
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        return AjaxResult.success(response.getData());
    }

    /**
     * 是否有未确认订单和未读消息
     */
    @ApiOperation(value = "是否有未确认订单和未读消息", notes = "是否有未确认订单和未读消息")
    @Log(title = "用户", businessType = BusinessType.OTHER)
    @GetMapping("/system/storageUser/unread")
    @ResponseBody
    public AjaxResult haveExistsUnConfirmOrderAndUnReadMessage(@RequestOperation OperationContext context) {
        ServiceResponse<JSONObject> response = storageUserService.haveExistsUnConfirmOrderAndUnReadMessage(context.getStorageUser());
        if (!response.isSuccess()) {
            return AjaxResult.error(response.getError());
        }
        return AjaxResult.success(response.getData());
    }
}
